type named = 
    | Var of string
    | Reg of string
    | In  of string
    | Out of string

let name_of x = match x with 
    | Var s -> s
    | Reg s -> s
    | In  s -> s
    | Out s -> s

type expression = 
    | Named  of named
    | Const  of int
    | Sum    of expression * expression
    | Prod   of expression * expression

module type Monad = sig
    type 'a t
    val return: 'a -> 'a t
    val bind: 'a t -> ('a -> 'a t) -> 'a t
end

module State : sig
    include Monad
    type 'a env
    val find:string -> 'a t -> 'a option
    val fst: 'a t -> 'a
    val snd: 'a t -> 'a env

end = struct
    type 'a env = (string * 'a) list
    type 'a t = 'a * ('a env)
    let return x = (x,[])
    let bind (x,e1) f = 
        let (y,e2) = f x in
            (y, List.append e1 e2)
    let find n (_,l) = 
        let hit (a,_) = (a == n) in 
            match List.find_opt hit l with
            | Some (_,b) -> Some(b)
            | None -> None
    let fst (x,_) = x
    let snd (_,l) = l
end

module Expression : sig
    include Monad
    val make_e: 'a -> string -> 'a t
    val fst: 'a t -> 'a
    val snd: 'a t -> string
end = struct
    type 'a t = 'a * string

    let return x = (x,"")

    let bind (x,s1) f = 
        let (y,s2) = f x in
            (y,s1^s2)

    let make_e x s = (x,s)

    let fst (x,_) = x
    let snd (_,s) = s

end

open Expression;;

let x = return (Const 4)
let y = return (Const 5)

let make_c c = match c with
| Const n -> make_e c (string_of_int n)
| _ -> failwith "not imp"

let ( +: ) a b = 
    let f x = make_e (Sum(x,(fst b))) (" + "^(snd b)) in
        bind a f

class component = object
val mutable symbolTable = []
method assign(a:named) (b:expression) = 
    symbolTable <- (a,b) :: symbolTable
end;;
(* 
type ('a, 'b) t = { mutable length: int;
buckets: ('a * 'b) list array;
}
The first field, length is declared as mutable. In OCaml, records are immutable by default, but individual fields are mutable when marked as such. The second field, buckets, is immutable, but contains an array, which is itself a mutable data structure.
Now we'll start putting together the basic functions for manipulating a dictionary. OCaml: imperative-programming/dictionary.ml (part 2)
let num_buckets = 17
let hash_bucket key = (Hashtbl.hash key) mod num_buckets
let create () = { length = 0;
buckets = Array.create ~len:num_buckets []; }
let length t = t.length
let find t key =
List.find_map t.buckets.(hash_bucket key)
~f:(fun (key',data) -> if key' = key then Some data else None)
 *)
module Component : Monad = struct 
    type 'a t = {
        self: 'a;
        symbol: (string*'a) list
    }
    
    let return x = {self = x;symbol = []}
    let bind x f = 
        let y = f x.self in 
        { self = y.self; symbol = List.append x.symbol y.symbol}
    let sym  x = x.symbol
    let expr x = x.self
    
 
end;;










